﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DcsGauges.Gui.Rendering;
using DcsGauges.Gui.Gauges.Interfaces;
using Microsoft.Xna.Framework.Graphics;
using DcsGauges.Shared.DataStructures;
using DcsGauges.DataStructures;
using DcsGauges.Gui.Gauges.Trigger;
using DcsGauges.Gui.Gauges.ValueConverters;
using Microsoft.Xna.Framework;

namespace DcsGauges.Gui.Gauges.Panels
{
    class EnvironmentPanel : GuiRenderableBase, IMultiTriggerGauge
    {
        #region Fields & Properties

        private Texture2D                                                                   backgroundTexture                   = null;
        private Dictionary<DcsProperty, Tuple<GuiRenderableBase, IValueGauge>>              subGauges                           = new Dictionary<DcsProperty, Tuple<GuiRenderableBase, IValueGauge>>();

        #endregion


        #region Constructos

        public EnvironmentPanel(GuiRenderableBase parent, URect area) : base(parent, area)
        {
            this.backgroundTexture                              = TextureManager.GetTexture("Textures/Panels/Backgrounds/Environment");

            TwoStateToggleSwitchGauge windshieldDefog           = new TwoStateToggleSwitchGauge(this, new URect(new ULoc(0.15f, 0.17f), new USize(0.12f, 0.12f)),
                DcsProperties.Panels.Right.Environment.WindShieldDefog,
                TextureManager.GetTexture("Textures/Gauges/Foregrounds/ToggleSwitchDown"),
                TextureManager.GetTexture("Textures/Gauges/Foregrounds/ToggleSwitchUp"),
                new TwoStateToggleSwitchConverter());

            AnalogRotatorSwitchGauge canopyDefog                = new AnalogRotatorSwitchGauge(this, new URect(new ULoc(0.395f, 0.16f), new USize(0.24f, 0.24f)), DcsProperties.Unknown, 
                TextureManager.GetTexture("Textures/Gauges/Foregrounds/RotatorKnob"), 
                new LinearConverter(new InOutMapping(0.0f, MathEx.Deg2Rad(0.0f)), new InOutMapping(1.0f, MathEx.Deg2Rad(90.0f)), MathEx.Deg2Rad(315.0f)));

            TwoStateToggleSwitchGauge  pitotHeat                = new TwoStateToggleSwitchGauge(this, new URect(new ULoc(0.145f, 0.38f), new USize(0.12f, 0.12f)), 
                DcsProperties.Panels.Right.Environment.PitotHeat,
                TextureManager.GetTexture("Textures/Gauges/Foregrounds/ToggleSwitchDown"), 
                TextureManager.GetTexture("Textures/Gauges/Foregrounds/ToggleSwitchUp"), 
                new TwoStateToggleSwitchConverter());

            TwoStateToggleSwitchGauge bleedAir                  = new TwoStateToggleSwitchGauge(this, new URect(new ULoc(0.75f, 0.38f), new USize(0.12f, 0.12f)), 
                DcsProperties.Panels.Right.Environment.BleedAir,
                TextureManager.GetTexture("Textures/Gauges/Foregrounds/ToggleSwitchDown"),
                TextureManager.GetTexture("Textures/Gauges/Foregrounds/ToggleSwitchUp"),
                new TwoStateToggleSwitchConverter());

            CircularGauge cabinPressure                         = new CircularGauge(this, new URect(new ULoc(0.4f, 0.48f), new USize(0.2f, 0.2f)), 
                DcsProperties.Panels.Right.Environment.CabinPressure,
                new LinearConverter(new InOutMapping(0.0f, MathEx.Deg2Rad(180.0f)), new InOutMapping(1.0f, MathEx.Deg2Rad(483.0f))),
                backgroundTexture:null, 
                arrowTexture: TextureManager.GetTexture("Textures/Gauges/Needles/EngineGaugesNeedle"));

            ThreeStateToggleSwitchGauge temperaturePress        = new ThreeStateToggleSwitchGauge(this, new URect(new ULoc(0.14f, 0.613f), new USize(0.12f, 0.12f)),
                DcsProperties.Panels.Right.Environment.TemperaturePressure,
                TextureManager.GetTexture("Textures/Gauges/Foregrounds/ToggleswitchDown"),
                TextureManager.GetTexture("Textures/Gauges/Foregrounds/ToggleswitchCenter"),
                TextureManager.GetTexture("Textures/Gauges/Foregrounds/ToggleswitchUp"),
                new ThreeStateToggleSwitchConverter());

            TwoStateToggleSwitchGauge mainAirSupply             = new TwoStateToggleSwitchGauge(this, new URect(new ULoc(0.75f, 0.613f), new USize(0.12f, 0.12f)),
                DcsProperties.Panels.Right.Environment.MainAirSupply,
                TextureManager.GetTexture("Textures/Gauges/Foregrounds/ToggleswitchDown"),
                TextureManager.GetTexture("Textures/Gauges/Foregrounds/ToggleswitchUp"),
                new TwoStateToggleSwitchConverter());

            AnalogRotatorSwitchGauge flowLevel                  = new AnalogRotatorSwitchGauge(this, new URect(new ULoc(0.2f, 0.8f), new USize(0.18f, 0.18f)), 
                DcsProperties.Panels.Right.Environment.FlowLevelControl,
                TextureManager.GetTexture("Textures/Gauges/Foregrounds/LoMedHiRotator"), 
                new LinearConverter(new InOutMapping(0.0f, MathEx.Deg2Rad(0.0f)), new InOutMapping(1.0f, MathEx.Deg2Rad(247.0f))));

            AnalogRotatorSwitchGauge tempLevel                  = new AnalogRotatorSwitchGauge(this, new URect(new ULoc(0.65f, 0.8f), new USize(0.18f, 0.18f)), 
                DcsProperties.Panels.Right.Environment.TemperatureLevel,
                TextureManager.GetTexture("Textures/Gauges/Foregrounds/LoMedHiRotator"), 
                new LinearConverter(new InOutMapping(0.0f, MathEx.Deg2Rad(0.0f)), new InOutMapping(1.0f, MathEx.Deg2Rad(247.0f))));

            ThreeStateToggleSwitchGauge tempOperator            = new ThreeStateToggleSwitchGauge(this, new URect(new ULoc(0.44f, 0.8f), new USize(0.12f, 0.12f)), 
                DcsProperties.Panels.Right.Environment.CabinAirOperator,
                TextureManager.GetTexture("Textures/Gauges/Foregrounds/ToggleswitchLeft"),
                TextureManager.GetTexture("Textures/Gauges/Foregrounds/ToggleswitchCenter"),
                TextureManager.GetTexture("Textures/Gauges/Foregrounds/ToggleswitchRight"),
                new IntervalStateConverter<ThreeStateToggleSwitchGauge.SwitchState>(
                    new List<Tuple<Interval,ThreeStateToggleSwitchGauge.SwitchState>>()
                    {
                        new Tuple<Interval, ThreeStateToggleSwitchGauge.SwitchState>(new Interval(-0.1f, 0.4f), ThreeStateToggleSwitchGauge.SwitchState.State0),
                        new Tuple<Interval, ThreeStateToggleSwitchGauge.SwitchState>(new Interval(0.41f, 0.6f), ThreeStateToggleSwitchGauge.SwitchState.State1),
                        new Tuple<Interval, ThreeStateToggleSwitchGauge.SwitchState>(new Interval(0.61f, 1.3f), ThreeStateToggleSwitchGauge.SwitchState.State2), 
                    }),
                    ThreeStateToggleSwitchGauge.Orientation.Horizontal);

            this.subGauges.Add(windshieldDefog.DataProperty,    new Tuple<GuiRenderableBase, IValueGauge>(windshieldDefog,      windshieldDefog));
            this.subGauges.Add(canopyDefog.DataProperty,        new Tuple<GuiRenderableBase, IValueGauge>(canopyDefog,          canopyDefog));
            this.subGauges.Add(pitotHeat.DataProperty,          new Tuple<GuiRenderableBase, IValueGauge>(pitotHeat,            pitotHeat));        
            this.subGauges.Add(bleedAir.DataProperty,           new Tuple<GuiRenderableBase, IValueGauge>(bleedAir,             bleedAir));
            this.subGauges.Add(cabinPressure.DataProperty,      new Tuple<GuiRenderableBase, IValueGauge>(cabinPressure,        cabinPressure));
            this.subGauges.Add(temperaturePress.DataProperty,   new Tuple<GuiRenderableBase, IValueGauge>(temperaturePress,     temperaturePress));
            this.subGauges.Add(mainAirSupply.DataProperty,      new Tuple<GuiRenderableBase, IValueGauge>(mainAirSupply,        mainAirSupply));
            this.subGauges.Add(flowLevel.DataProperty,          new Tuple<GuiRenderableBase, IValueGauge>(flowLevel,            flowLevel));      
            this.subGauges.Add(tempLevel.DataProperty,          new Tuple<GuiRenderableBase, IValueGauge>(tempLevel,            tempLevel));
            this.subGauges.Add(tempOperator.DataProperty,       new Tuple<GuiRenderableBase, IValueGauge>(tempOperator,         tempOperator));
        }

        #endregion


        #region Interface Implementation

        #region Events

        public event EventHandler<TriggerValueEventArgs>  TriggerEvent;

        #endregion

        #region Properties
        
        public Shared.DataStructures.DcsProperty[] Properties
        {
            get { return this.subGauges.Keys.ToArray(); }
        }

        public void SetValue(Shared.DataStructures.DcsProperty property, float value)
        {
            this.subGauges[property].Item2.Value = value;
        }

        public float GetValue(Shared.DataStructures.DcsProperty property)
        {
            return this.subGauges[property].Item2.Value;
        }

        #endregion

        #endregion


        #region Overrides

        public override void Render(SpriteBatch spriteBatch, GraphicsDevice device, Rectangle parentRect, float globalZIndex)
        {
            Rectangle? originalDim              = this.keepAspectRatio ? this.backgroundTexture.Bounds : new Rectangle?();
            Rectangle viewPortRect              = base.CalcViewportRect(parentRect, originalDim);

            spriteBatch.Draw(this.backgroundTexture, viewPortRect, null, Color.White, 0.0f, Vector2.Zero, SpriteEffects.None, base.NextFrontIndex(globalZIndex, 1));

            foreach (var sg in this.subGauges.Values)
            {
                GuiRenderableBase renderable = sg.Item1;
                renderable.Render(spriteBatch, device, viewPortRect, base.NextFrontIndex(globalZIndex, 2));
            }
        }

        #endregion
    }
}
